#include "dlist.h"


/**
 * @brief 创建双向链表
 * 
 * @return node_t* 链表头节点指针
 */
node_t *create_dlist()
{
	node_t *head = malloc(sizeof(node_t));
	head->data = NULL;
	head->before = head;
	head->after = head;
	return head;
}


/**
 * @brief 头部插入节点
 * 
 * @param head 链表头指针
 * @param data 要插入的数据指针
 * @param size 数据大小
 * @return int 操作状态(0=成功, -1=失败)
 */
int insert_hdlist(node_t *head,const void *data,int size)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(NULL,==,data,"data is NULL",-1);
	SYSERR(size,<,0,"error:size < 0",-1);

	//创建节点
	node_t *newnode = malloc(sizeof(node_t));
	newnode->data = malloc(size);

	//初始化值
	memcpy(newnode->data,data,size);//直接复制一块内存区域

	//初始化指针
	newnode->before = head;
	newnode->after = head->after;
	head->after->before = newnode;
	head->after = newnode;
	return 0;
}


/**
 * @brief 从前往后遍历链表
 * 
 * @param head 链表头指针
 * @param showfun 节点数据显示函数
 */
void show_hdlist(node_t *head,showfun_t showfun)
{
	SYSERR(NULL,==,head,"head is NULL",);
	SYSERR(head->after,==,head,"dlist is empty",);

	node_t *temp = head->after;
	while(1)
	{
		showfun(temp->data);
		if(temp->after == head)
			break;
		temp = temp->after;
	}
}


/**
 * @brief 从后往前遍历链表
 * 
 * @param head 链表头指针
 * @param showfun 节点数据显示函数
 */
void show_tdlist(node_t *head,showfun_t showfun)
{
	SYSERR(NULL,==,head,"head is NULL",);
	SYSERR(head->before,==,head,"dlist is empty",);

	node_t *temp = head->before;
	while(1)
	{
		showfun(temp->data);
		if(temp->before == head)
			break;
		temp = temp->before;
	}

}


/**
 * @brief 尾部插入节点
 * 
 * @param head 链表头指针
 * @param data 要插入的数据指针
 * @param size 数据大小
 * @return int 操作状态(0=成功, -1=失败)
 */
int insert_tdlist(node_t *head,const void *data,int size)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(NULL,==,data,"data is NULL",-1);
	SYSERR(size,<,0,"error:size < 0",-1);

	node_t *newnode = malloc(sizeof(node_t));
	newnode->data = malloc(size);

	memcpy(newnode->data,data,size);

	newnode->after = head;
	newnode->before = head->before;
	head->before->after = newnode;
	head->before = newnode;

	return 0;
}


/**
 * @brief 按值查找节点
 * 
 * @param head 链表头指针
 * @param value 要查找的值指针
 * @param cmpfun 比较函数指针
 * @return node_t* 找到的节点指针(未找到返回NULL)
 */
node_t *find_vdlist(node_t *head,const void *value,cmpfun_t cmpfun)
{
	SYSERR(NULL,==,head,"head is NULL",NULL);
	SYSERR(NULL,==,value,"value is NULL",NULL);
	SYSERR(head->after,==,head,"dlist is empty",NULL);

	node_t *temp = head->after;
	while(1)
	{
		if(!(cmpfun(temp->data,value)))
			break;
		if(temp->after == head)
			return NULL;
		temp = temp->after;
	}
	return temp;
}


/**
 * @brief 更新节点数据
 * 
 * @param head 链表头指针
 * @param olddata 原数据指针
 * @param newdata 新数据指针
 * @param cmpfun 比较函数指针
 * @param updatefun 更新函数指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int update_dlist(node_t *head,void *olddata,void *newdata,cmpfun_t cmpfun,updatefun_t updatefun)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(NULL,==,olddata,"olddata is NULL",-1);
	SYSERR(NULL,==,newdata,"newdata is NULL",-1);
	SYSERR(head->after,==,head,"dlist is empty",-1);

	node_t *temp = find_vdlist(head,olddata,cmpfun);
	if(NULL == temp)
	{
		printf("not found\n");
		return -1;
	}
	return updatefun(temp->data,newdata);
}


/**
 * @brief 删除头部节点
 * 
 * @param head 链表头指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int delete_hdlist(node_t *head)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(head->after,==,head,"dlist is empty",-1);

	node_t *temp = head->after;
	head->after = temp->after;
	temp->after->before = head;
	free(temp->data);
	free(temp);
	return 0;
}


/**
 * @brief 删除尾部节点
 * 
 * @param head 链表头指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int delete_tdlist(node_t *head)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(head->after,==,head,"dlist is empty",-1);

	node_t *temp = head->before;
	head->before = temp->before;
	temp->before->after = head;
	free(temp->data);
	free(temp);
	return 0;
}


/**
 * @brief 按值删除节点
 * 
 * @param head 链表头指针
 * @param value 要删除的值指针
 * @param cmpfun 比较函数指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int delete_vdlist(node_t *head,void *value,cmpfun_t cmpfun)
{
	SYSERR(NULL,==,head,"head is NULL",-1);
	SYSERR(NULL,==,value,"value is NULL",-1);
	SYSERR(head->after,==,head,"dlist is empty",-1);

	node_t *temp = find_vdlist(head,value,cmpfun);
	if(NULL == temp)
		return -1;
	temp->before->after = temp->after;
	temp->after->before = temp->before;
	free(temp->data);
	free(temp);
	return 0;
}


/**
 * @brief 销毁整个链表
 * 
 * @param head 链表头指针的指针
 * @return int 操作状态(0=成功, -1=失败)
 */
int destroy_dlist(node_t **head)
{
	SYSERR(NULL,==,*head,"head is NULL",-1);

	node_t *temp = (*head)->after;
	node_t *after = temp->after;

	while(1)
	{
		after = temp->after;
		if(temp == *head)
			break;
		free(temp->data);
		free(temp);
		temp = after;
	}

	free(*head);
	*head = NULL;
	return 0;
}
